package com.ctvit.sjk.knowledge.document.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctvit.sjk.knowledge.core.constant.KnowledgeConstant;
import com.ctvit.sjk.knowledge.dataset.pojo.domain.TabDataset;
import com.ctvit.sjk.knowledge.document.mapper.TabDocumentMapper;
import com.ctvit.sjk.knowledge.document.pojo.domain.TabDocument;
import com.ctvit.sjk.knowledge.document.pojo.dto.DocumentBatchCreateDTO;
import com.ctvit.sjk.knowledge.document.pojo.dto.DocumentBatchDeleteDTO;
import com.ctvit.sjk.knowledge.document.pojo.dto.DocumentBatchRefreshDTO;
import com.ctvit.sjk.knowledge.document.pojo.dto.DocumentCancelTaskDTO;
import com.ctvit.sjk.knowledge.document.pojo.dto.DocumentRefreshDTO;
import com.ctvit.sjk.knowledge.document.pojo.vo.DocumentGetVO;
import com.ctvit.sjk.knowledge.document.pojo.dto.DocumentQueryDTO;
import com.ctvit.sjk.knowledge.document.service.ITabDocumentService;
import com.ctvit.sjk.knowledge.paragraph.pojo.domain.TabParagraph;
import com.ctvit.sjk.knowledge.paragraph.pojo.dto.ParagraphCreateDTO;
import com.ctvit.sjk.knowledge.paragraph.service.ITabParagraphService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 文档Service业务层处理
 *
 * @author heyingcheng
 * @date 2025/3/22
 */
@Slf4j
@Service
public class TabDocumentServiceImpl extends ServiceImpl<TabDocumentMapper, TabDocument> implements ITabDocumentService {

    private final ITabParagraphService tabParagraphService;

    public TabDocumentServiceImpl(ITabParagraphService tabParagraphService) {
        this.tabParagraphService = tabParagraphService;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<DocumentGetVO> batchCreate(TabDataset tabDataset, List<DocumentBatchCreateDTO> dtoList, String userId) {
        String datasetId = tabDataset.getDatasetId();
        List<String> ids = new ArrayList<>(dtoList.size());
        dtoList.forEach(docDTO -> {
            String documentId = IdWorker.getIdStr();
            int charLength = 0;
            int paragraphCount = 0;

            List<ParagraphCreateDTO> paragraphList = docDTO.getParagraphList();
            if (CollectionUtils.isNotEmpty(paragraphList)) {
                paragraphCount = paragraphList.size();

                for (ParagraphCreateDTO paraDTO : paragraphList) {
                    TabParagraph paraEntity = new TabParagraph();
                    paraEntity.setParagraphId(IdWorker.getIdStr());
                    paraEntity.setDatasetId(datasetId);
                    paraEntity.setDocumentId(documentId);
                    paraEntity.setParagraphTitle(paraDTO.getName());

                    String content = StringUtils.defaultString(paraDTO.getContent());
                    int contentLength = content.length();
                    charLength += contentLength;

                    paraEntity.setParagraphContent(content);
                    paraEntity.setCharLength(contentLength);
                    paraEntity.setStatusMetadata(KnowledgeConstant.JSON_OBJECT_EMPTY);
                    paraEntity.setCreateId(userId);
                    paraEntity.setCreateTime(LocalDateTime.now());
                    paraEntity.setUpdateId(userId);
                    paraEntity.setUpdateTime(LocalDateTime.now());
                    tabParagraphService.save(paraEntity);
                }
            }

            TabDocument docEntity = new TabDocument();
            docEntity.setDocumentId(documentId);
            docEntity.setDatasetId(datasetId);
            docEntity.setDocumentName(docDTO.getName());
            docEntity.setDocumentType(tabDataset.getDatasetType());
            docEntity.setDocumentMetadata(KnowledgeConstant.JSON_OBJECT_EMPTY);
            docEntity.setStatusMetadata(KnowledgeConstant.JSON_OBJECT_EMPTY);
            docEntity.setParagraphCount(paragraphCount);
            docEntity.setCharLength(charLength);
            docEntity.setCreateId(userId);
            docEntity.setCreateTime(LocalDateTime.now());
            docEntity.setUpdateId(userId);
            docEntity.setUpdateTime(LocalDateTime.now());
            save(docEntity);

            ids.add(docEntity.getDocumentId());
        });

        List<TabDocument> tabDocuments = listByIds(ids);

        return tabDocuments.stream().map(DocumentGetVO::new).collect(Collectors.toList());
    }

    @Override
    public List<DocumentGetVO> list(String datasetId, DocumentQueryDTO dto) {
        LambdaQueryWrapper<TabDocument> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TabDocument::getDatasetId, datasetId);
        wrapper.like(StringUtils.isNotBlank(dto.getName()), TabDocument::getDocumentName, dto.getName());
        wrapper.eq(StringUtils.isNotBlank(dto.getHitHandlingMethod()), TabDocument::getHitHandlingMethod, dto.getHitHandlingMethod());
        wrapper.eq(Objects.nonNull(dto.getActiveFlag()), TabDocument::getActiveFlag, dto.getActiveFlag());

        String orderBy = dto.getOrderBy();
        if (StringUtils.isNotBlank(orderBy)) {
            SFunction<TabDocument, ?> jqlParserFunction = null;

            if (orderBy.contains("char_length")) {
                jqlParserFunction = TabDocument::getCharLength;
            } else if (orderBy.contains("paragraph_count")) {
                jqlParserFunction = TabDocument::getParagraphCount;
            } else if (orderBy.contains("create_time")) {
                jqlParserFunction = TabDocument::getCreateTime;
            }

            if (Objects.nonNull(jqlParserFunction)) {
                if (dto.getOrderBy().startsWith("-")) {
                    wrapper.orderByDesc(jqlParserFunction);
                } else {
                    wrapper.orderByAsc(jqlParserFunction);
                }
            }
        }

        return list(wrapper).stream().map(DocumentGetVO::new).collect(Collectors.toList());
    }

    @Override
    public boolean refresh(String datasetId, String documentId, DocumentRefreshDTO dto, String userId) {
        DocumentBatchRefreshDTO batchRefreshDTO = new DocumentBatchRefreshDTO();
        batchRefreshDTO.setIdList(Collections.singletonList(documentId));
        batchRefreshDTO.setStateList(dto.getStateList());

        return batchRefresh(datasetId, batchRefreshDTO, userId);
    }

    @Override
    public boolean cancelTask(String datasetId, String documentId, DocumentCancelTaskDTO dto, String userId) {
        log.info("datasetId:[{}], documentId:[{}]", datasetId, documentId);
        return true;
    }

    @Override
    public boolean batchRefresh(String datasetId, DocumentBatchRefreshDTO dto, String userId) {
        LambdaUpdateWrapper<TabDocument> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(TabDocument::getDocumentStatus, "nnn");
        wrapper.set(TabDocument::getUpdateId, userId);
        wrapper.set(TabDocument::getUpdateTime, LocalDateTime.now());
        wrapper.eq(TabDocument::getDatasetId, datasetId);
        wrapper.in(TabDocument::getDocumentId, dto.getIdList());
        wrapper.in(TabDocument::getDocumentStatus, dto.getStateList());

        return update(wrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean batchDelete(String datasetId, DocumentBatchDeleteDTO dto, String userId) {
        List<String> idList = dto.getIdList();
        for (String id : idList) {
            LambdaUpdateWrapper<TabParagraph> paraWrapper = new LambdaUpdateWrapper<>();
            paraWrapper.set(TabParagraph::getUpdateId, userId);
            paraWrapper.set(TabParagraph::getUpdateTime, LocalDateTime.now());
            paraWrapper.eq(TabParagraph::getDocumentId, id);
            tabParagraphService.remove(paraWrapper);

            LambdaUpdateWrapper<TabDocument> wrapper = new LambdaUpdateWrapper<>();
            wrapper.set(TabDocument::getUpdateId, userId);
            wrapper.set(TabDocument::getUpdateTime, LocalDateTime.now());
            wrapper.eq(TabDocument::getDocumentId, id);
            wrapper.eq(TabDocument::getDatasetId, datasetId);
            remove(wrapper);
        }
        return false;
    }

}
